package org.itboys.weixin.service;

import java.util.Date;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import org.itboys.weixin.dto.SendArticle;
import org.itboys.weixin.entity.WeixinConfig;
import org.itboys.weixin.entity.WeixinSendRecord;
import org.itboys.weixin.tools.WeixinSendUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * 微信推送相关 请在配置文件里加上
 *  <bean id="weixinPush" class="com.hz.sunday.weixin.bo.WeixinPush">
		<property name="coreSize" value="40"></property>
	</bean>
 * @author ChenJunhui
 *
 */
public class WeixinPush {

	private static  Logger logger = LoggerFactory.getLogger(WeixinCoreService.class);
	
	private static int MAX_USER=500;//每次从数据库中抓多少条用户出来发
	
	@Autowired
	private WeixinUserService weixinUserService;
	
	@Autowired
	private WeixinConfigService weixinConfigService;
	
	@Autowired
	private WeixinSendRecordService weixinSendRecordService;
	
	private int coreSize; //发送消息线程池容量 bean 注入
	
	/**
	 * 推送微信文本消息给关注微信的用户
	 * @param sendRecordId 推送记录ID
	 * @param weixinId
	 * @param messageId
	 */
	public void doSend(long sendRecordId,long weixinId,String content,int isTest){
		long minUserId = weixinUserService.getMinUserId(weixinId);
		doSend(minUserId, sendRecordId, weixinId, content,isTest);
	}
	
	/**
	 * 推送微信文本消息给关注微信的用户
	 * @param sendRecordId 推送记录ID
	 * @param weixinId
	 * @param messageId
	 */
	public void doSend(long sendRecordId,long weixinId,List<SendArticle> articles,int isTest){
		long minUserId = weixinUserService.getMinUserId(weixinId);
		doSend(minUserId, sendRecordId, weixinId, articles,isTest);
	}
	
	/**
	 * 推送微信文本消息给关注微信的用户
	 * @param minUserId weixin_user表中 weixin_id=? 的最小的 id
	 * @param sendRecordId 推送记录ID
	 * @param weixinId
	 * @param messageId
	 */
	public void doSend(long minUserId,long sendRecordId,long weixinId,String content,int isTest){
		WeixinConfig weixin = weixinConfigService.getById(weixinId);
		List<String> openids = weixinUserService.getWeixinUsers(weixinId, minUserId-1, MAX_USER,isTest);
		System.out.println(openids.size());
		doSend(sendRecordId, weixin.getAppId(), weixin.getAppSecret(), content, openids);
		Long id = weixinUserService.getId(weixinId, openids.get(openids.size()-1));
		if(openids.size()==MAX_USER){
			//数据库还有数据的话就继续调
			doSend(id, sendRecordId, weixinId, content,isTest);
		}else{
			WeixinSendRecord record = weixinSendRecordService.getById(sendRecordId);
			record.setEndTime(new Date());
			weixinSendRecordService.update(record);
		}
	}
	
	/**
	 * 推送微信文本消息给关注微信的用户
	 * @param minUserId weixin_user表中 weixin_id=? 的最小的 id
	 * @param sendRecordId 推送记录ID
	 * @param weixinId
	 * @param messageId
	 */
	public void doSend(long minUserId,long sendRecordId,long weixinId,List<SendArticle> articles,int isTest){
		WeixinConfig weixin = weixinConfigService.getById(weixinId);
		List<String> openids = weixinUserService.getWeixinUsers(weixinId, minUserId-1, MAX_USER,isTest);
		doSend(sendRecordId, weixin.getAppId(), weixin.getAppSecret(), articles, openids);
		Long id = weixinUserService.getId(weixinId, openids.get(openids.size()-1));
		if(openids.size()==MAX_USER){
			//数据库还有数据的话就继续调
			doSend(id, sendRecordId, weixinId, articles,isTest);
		}else{
			WeixinSendRecord record = weixinSendRecordService.getById(sendRecordId);
			record.setEndTime(new Date());
			weixinSendRecordService.update(record);
		}
	}
	
	/**
	 * 推送微信图文消息给关注微信的用户
	 * @param sendRecordId 推送记录ID
	 * @param weixinId
	 * @param messageId
	 */
	private void doSend(long sendRecordId,String appId,String appSecret, List<SendArticle> articles ,List<String> openids){
		ExecutorService pool = Executors.newFixedThreadPool(coreSize); 
		CompletionService<Integer> completionService = new ExecutorCompletionService<Integer>(pool);
		int size = openids.size();
		int successCount = 0;
		int failCount = 0;
		try{
			for(int i=0;i<size;i++){
				completionService.submit(new SendArticleTask(appId, appSecret, openids.get(i), articles));
			}
			for(int i=0;i<size;i++){
				try {
					Future<Integer> future = completionService.take();  
					int result = future.get();
					if(result==1){
						successCount++;
					}else{
						failCount++;
					}
				} catch (Exception e) {
					logger.error("sendMessages error", e);
				} 
			}
			WeixinSendRecord record = weixinSendRecordService.getById(sendRecordId);
			record.setSuccessCount(successCount);
			record.setFailCount(failCount);
			weixinSendRecordService.update(record);
		}catch(Exception e){
			logger.error("WeixinPush.doSendArticle Exception", e);
		}finally{
			pool.shutdown();
		}
	}
	
	/**
	 * 推送微信文本消息给关注微信的用户
	 * @param sendRecordId 推送记录ID
	 * @param weixinId
	 * @param messageId
	 */
	private void doSend(long sendRecordId,String appId,String appSecret, String content ,List<String> openids){
		ExecutorService pool = Executors.newFixedThreadPool(coreSize); 
		CompletionService<Integer> completionService = new ExecutorCompletionService<Integer>(pool);
		int size = openids.size();
		int successCount = 0;
		int failCount = 0;
		try{
			for(int i=0;i<size;i++){
				completionService.submit(new SendTextTask(appId, appSecret, openids.get(i), content));
			}
			for(int i=0;i<size;i++){
				try {
					Future<Integer> future = completionService.take();  
					int result = future.get();
					if(result==1){
						successCount++;
					}else{
						failCount++;
					}
				} catch (Exception e) {
					logger.error("sendMessages error", e);
				} 
			}
			WeixinSendRecord record = weixinSendRecordService.getById(sendRecordId);
			record.setSuccessCount(successCount);
			record.setFailCount(failCount);
			weixinSendRecordService.update(record);
		}catch(Exception e){
			logger.error("WeixinPush.doSend Exception", e);
		}finally{
			pool.shutdown();
		}
	}
	
	
	/**
	 * 发送文本消息的线程
	 * @author ChenJunhui
	 *
	 */
    class SendTextTask implements Callable<Integer>{
    	
    	private String openid;//微信用户的ID
    	private String content;//推送内容
    	private String appId;
    	private String appSecret;
    	
    	public SendTextTask(String appId,String appSecret,String openid,String content){
    		this.openid=openid;
    		this.appId=appId;
    		this.appSecret=appSecret;
    		this.content=content;
    	}
    	
		@Override
		public Integer call() throws Exception {
			return WeixinSendUtils.sendMessage(appId, appSecret, openid, content);
		}
    }
    
    /**
	 * 发送图文消息的线程
	 * @author ChenJunhui
	 *
	 */
    class SendArticleTask implements Callable<Integer>{
    	
    	private String openid;//微信用户的ID
    	private List<SendArticle> articles;//推送内容
    	private String appId;
    	private String appSecret;
    	
    	public SendArticleTask(String appId,String appSecret,String openid,List<SendArticle> articles){
    		this.openid=openid;
    		this.appId=appId;
    		this.appSecret=appSecret;
    		this.articles=articles;
    	}
    	
		@Override
		public Integer call() throws Exception {
			return WeixinSendUtils.sendMessage(appId, appSecret, openid, articles);
		}
    }

	public void setCoreSize(int coreSize) {
		this.coreSize = coreSize;
	}
}
